import { find, isArray, get, first, map, intersection, isEqual, isEmpty, filter } from "lodash";
import React from "react";
import PropTypes from "prop-types";
import Radio from "antd/lib/radio";
import Checkbox from "antd/lib/checkbox";
import TreeSelect from "antd/lib/tree-select";
import SelectWithVirtualScroll from "@/components/SelectWithVirtualScroll";
import { currentUser } from "@/services/auth";

function findChildren(filteroptions, key) {
  let items = [];
  let children = filter(filteroptions, r => r["parent"].toString() === key.toString());

  map(children, d=>{
    const c = findChildren(filteroptions, d["value"]);
    items.push({
      value: d["value"], 
      title: d["name"], 
      children: c,
    })
  }) 

  return items;
}

export default class QueryBasedParameterInput extends React.Component {
  static propTypes = {
    parameter: PropTypes.any, // eslint-disable-line react/forbid-prop-types
    value: PropTypes.any, // eslint-disable-line react/forbid-prop-types
    mode: PropTypes.oneOf(["default", "multiple"]),
    queryId: PropTypes.number,
    onSelect: PropTypes.func,
    className: PropTypes.string,
  };

  static defaultProps = {
    value: null,
    mode: "default",
    parameter: null,
    queryId: null,
    onSelect: () => {},
    className: "",
  };

  constructor(props) {
    super(props);
    this.state = {
      options: [],
      value: null,
      loading: false,
    };
  }

  componentDidMount() {
    this._loadOptions(this.props.queryId);
  }

  componentDidUpdate(prevProps) {
    if (this.props.queryId !== prevProps.queryId) {
      this._loadOptions(this.props.queryId);
    }
    if (this.props.value !== prevProps.value) {
      this.setValue(this.props.value);
    }
  }

  setValue(value) {
    const { options } = this.state;
    if (this.props.mode === "multiple") {
      value = isArray(value) ? value : [value];
      const optionValues = map(options, option => option.value);
      const validValues = intersection(value, optionValues);
      this.setState({ value: validValues });
      return validValues;
    }
    const found = find(options, option => option.value === this.props.value) !== undefined;
    value = found ? value : get(first(options), "value");
    this.setState({ value });
    return value;
  }

  async _loadOptions(queryId) {
    if (queryId && queryId !== this.state.queryId) {
      this.setState({ loading: true });
      const options = await this.props.parameter.loadDropdownValues();

      // stale queryId check
      if (this.props.queryId === queryId) {
        this.setState({ options, loading: false }, () => {
          const updatedValue = this.setValue(this.props.value);
          if (!isEqual(updatedValue, this.props.value)) {
            this.props.onSelect(updatedValue);
          }
        });
      }
    }
  }

  render() {
    const { className, mode, onSelect, queryId, value, parameter, ...otherProps } = this.props;
    const { loading, options } = this.state;

    //处理filter同步url
    var filteroptions = options;
    var new_value = this.state.value;
    if (options && options.length>0) {
      let filterfileds = Object.keys(options[0]).filter(key => key.includes("::filter") || key.includes("::multi-filter"));
      filterfileds.map((filterfiled) => {
        const filterfiledstr = filterfiled.split("::")[0].toLowerCase();
        const paramterstr = "_" + filterfiledstr;
        var isDefault = true;
        filteroptions = filteroptions.filter((option) => {
          if (currentUser && filterfiledstr.indexOf("currentuser_") === 0) {
            const userProperty = filterfiledstr.substring(12);
            if (currentUser.hasOwnProperty(userProperty)) {
              if (String(option[filterfiled]) === String(currentUser[userProperty])) {
                if (isDefault) {
                  isDefault = false;
                  if (!parameter.multiValuesOptions && option.value !== new_value) new_value = option.value;
                }
                if (!parameter.multiValuesOptions && option.value === this.state.value) new_value = this.state.value;
                return true;
              } else {
                return false;
              }
            }
          } else {
            var parameterValue = "";
            var searchURL = window.location.search.toLowerCase();
            if (searchURL.includes(paramterstr) && searchURL.indexOf(paramterstr + "=") > 0) {
              searchURL = searchURL.substring(searchURL.indexOf(paramterstr + "="), searchURL.length);
              parameterValue = decodeURIComponent(searchURL.split("&")[0].split("=")[1]);
              if (String(option[filterfiled]) === parameterValue || 
                (JSON.parse(parameterValue) instanceof Array && JSON.parse(parameterValue).indexOf(String(option[filterfiled]))>=0) ) {
                if (isDefault) {
                  isDefault = false;
                  if (!parameter.multiValuesOptions && option.value !== new_value) new_value = option.value;
                }
                if (!parameter.multiValuesOptions && option.value === this.state.value) new_value = this.state.value;
                return true;
              } else {
                return false;
              }
            }
          }

          if (option.value === this.state.value) new_value = this.state.value;
          return true;
        });
        return null;
      });
    }

    if (!parameter.multiValuesOptions && new_value !== this.state.value) this.setState({ value: new_value});

    const showPortal = window.location.search.includes("show_portal") && localStorage.getItem('colorstyle_mode');

    if (!parameter.tileDisplay && !!parameter.treeDisplay) {
      let treeData = [];
      map(filter(filteroptions, r => (r["parent"]===undefined || r["parent"]===null || r["parent"]==='')), d => {
        const c = findChildren(filter(filteroptions, r => (r["parent"]!==undefined && r["parent"]!==null && r["parent"]!=='')), d["value"]);
        treeData.push({
          value: d["value"], 
          title: d["name"], 
          children: c,
        });
      });
        
      const cssStyle = {
        width: '100%',
        minWidth: '200px',
      };
    
      return (
        <span>
        <TreeSelect
          className={className}
          style={cssStyle}
          treeData={treeData}
          value={!!this.state.value ? this.state.value : null}
          treeDefaultExpandAll
          placeholder="请选择"
          dropdownMatchSelectWidth={false}
          treeCheckable={!!parameter.multiValuesOptions ? true : false}
          showCheckedStrategy={TreeSelect.SHOW_PARENT}
          onChange={onSelect}
        />
        </span>
      );
    } else if (parameter.tileDisplay && parameter.multiValuesOptions)
      return (
        <Radio.Button
          style={showPortal ? {backgroundColor: "#00000000", color: localStorage.getItem("colorstyle_color"), height: '35px'} : {height: '35px'}}
        >
        <Checkbox.Group
          defaultValue={ this.state.value instanceof Array && this.state.value}
          onChange={onSelect}
        >
          {map(filteroptions, ({ value, name })  => (<Checkbox value={value}>{String(name)}</Checkbox>))}
        </Checkbox.Group>
        </Radio.Button>
      );
    else if (parameter.tileDisplay)
      return (
        <Radio.Group
          buttonStyle="outline"        
          value={this.state.value}
          onChange={e => onSelect(e.target.value)}
        >
          {map(filteroptions, ({ value, name })  => (
            <Radio.Button value={value}
              style={showPortal ? {backgroundColor: "#00000000", color: localStorage.getItem("colorstyle_color"), height: '35px'} : {height: '35px'}}
            >
              {String(name)}
            </Radio.Button>))}
        </Radio.Group>
      );
    else
    return (
      <span>
        <SelectWithVirtualScroll
          className={className}
          disabled={loading}
          loading={loading}
          mode={mode}
          value={this.state.value}
          onChange={onSelect}
          options={map(filteroptions, ({ value, name }) => ({ label: String(name), value }))}
          optionFilterProp="label"
          showSearch
          showArrow
          notFoundContent={isEmpty(filteroptions) ? "没有可选数据" : null}
          {...otherProps}
        />
      </span>
    );
  }
}
